<?php

namespace interface\v1;
/*
*审批接口类
*/

use control\auditClass;
use control\PYClass;
use verify;

class auditAppClass extends index
{
    private const title = '审批接口类';
    public const whiteField = [
        '全部',
        '付款申请',
        '费用报销',
        '费用申请',
        '外出申请',
        '外出成果审核',
        '出差申请',
        '出差成果审核',
        '加班申请',
        '加班成果审核',
        '补卡申请',
        '请假申请',
    ];

    /**
     * 获取员工信息
     */
    public function getStaffInfo()
    {
        $stid = $this->post('staffId');
        $staff = query('staff', "stid = '$stid'");
        if (empty($staff['stid'])) {
            $this->resp['warn'] = '未找到此员工';
        } else {
            $this->code = 1;
            $job = query('job', "id = '$staff[jobId]'");
            $this->resp['data']['result'][] = [
                'stid' => $staff['stid'],
                'ico' => self::fillSrc($staff['ico']),
                'name' => $staff['name'],
                'department' => self::findStaffDepartment($staff['stid']),
                'job' => $job['name']
            ];
        }
    }

    /*查询条件*/
    public function search()
    {
        //状态
        $data['result']['flowOption'] = self::whiteField;
        $data['result']['timeOption'] = $this->timeOption;
        $data['result']['stateOption'] = ['草稿', '审核中', '已通过'];
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }

    /*发起审批*/
    public function home()
    {
        $userPower = self::getUserPower();
        $data['result']['menu'] = [
            [
                'name' => '人力资源',
                'array' => [
                    [
                        'name' => '补卡申请',
                        'ico' => oaIndexAppClass::icon('workSignAdd'),
                        'power' => 'workSignAdd',
                        'url' => '/oa/pages/workSignAdd/workSignAdd',
                    ],
                    [
                        'name' => '请假申请',
                        'ico' => oaIndexAppClass::icon('holiday'),
                        'power' => 'work',
                        'url' => '/oa/pages/workHoliday/workHoliday',
                    ],
                    [
                        'name' => '外出申请',
                        'ico' => oaIndexAppClass::icon('out'),
                        'power' => 'workOut',
                        'url' => '/oa/pages/workOut/workOut',
                    ],
                    [
                        'name' => '加班申请',
                        'ico' => oaIndexAppClass::icon('workAdd'),
                        'power' => 'workAdd',
                        'url' => '/oa/pages/work/work',
                    ],
                    [
                        'name' => '出差申请',
                        'ico' => oaIndexAppClass::icon('bussinessTrip'),
                        'power' => 'bussinessTrip',
                        'url' => '/oa/pages/bussinessTrip/bussinessTrip',
                    ],
                ]
            ],
            [
                'name' => '财务管理',
                'array' => [
                    [
                        'name' => '费用申请',
                        'ico' => oaIndexAppClass::icon('feeApply'),
                        'power' => 'feeApply',
                        'url' => '/oa/pages/feeApply/feeApply',
                    ],
                    [
                        'name' => '报销申请',
                        'ico' => oaIndexAppClass::icon('cost'),
                        'power' => 'cost',
                        'url' => '/oa/pages/cost/cost',
                    ],
                    [
                        'name' => '付款申请',
                        'ico' => oaIndexAppClass::icon('payment'),
                        'power' => 'payment',
                        'url' => '/oa/pages/payment/payment',
                    ],
                ]
            ]
        ];
        foreach ($data['result']['menu'] as $index => $array) {
            foreach ($array['array'] as $num => $val) {
                if (!array_key_exists($val['power'], $userPower)) {
                    unset($data['result']['menu'][$index]['array'][$num]);
                }
            }
            if (self::is_null_array($data['result']['menu'][$index]['array'])) {
                unset($data['result']['menu'][$index]);
            }
        }
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }

    /**
     * 列表页
     */
    public function waitlist()
    {

        //全等查询数组
        $equal = array(
            'workFlow' => '审核中',
            'applicantId' => $this->post('applicantId'),
            'flowName' => $this->post('flowName') == '全部' ? '' : $this->post('flowName'),
        );
        $like = array(
            "approverId" => self::$stid,//员工
        );
        //初始化
        $and = " and flowName in ('" . implode("','", self::whiteField) . "')";
        if ($this->post('keyword')) {
            $and .= " and (flowName like '%" . $this->post('keyword') . "%' or orderNo like '%" . $this->post('keyword') . "%')";
        }
        $commitTime = $this->post('commit_time');
        if (!$commitTime) {
            if ($this->post('startDate')) {
                $commitTime = $this->post('startDate');
            }
            if ($this->post('endDate')) {
                $commitTime .= empty($commitTime) ? $this->post('endDate') : ('~' . $this->post('endDate'));
            }
        }
        if ($commitTime) {
            $and .= self::miniTimeComparison($commitTime, 'date', 'commitTime');
        }

        //获取查询结果
        $where = search(array("=" => $equal, 'like' => $like)) . $and;
        $page = $this->page(array("table" => 'audit', "where" => $where, "order" => "commitTime desc"));
        //数据分析
        $data['result'] = [];
        foreach ($page['array'] as $array) {

            switch ($array['flowName']) {
                case '补卡申请';
                    $info = query('work_sign_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '补卡时间点：' . $info['signTime'],
                        'lineTwo' => '补卡事由：' . $info['text'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/workSignAddInfo/workSignAdInfo?id=' . $info['id'];
                    break;
                case '请假申请';
                    $info = query('work_holiday', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '分类：' . $info['type'],
                        'lineTwo' => '开始时间：' . $info['startTime'],
                        'lineThree' => '结束时间：' . $info['endTime'],
                    ];
                    $url = '/oa/pages/workHolidayInfo/workHolidayInfo?id=' . $info['id'];
                    break;
                case '外出申请';
                case '外出成果审核';
                    $info = query('work_out', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '外出事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workOutInfo/workOutInfo?id=' . $info['id'];
                    break;
                case '出差申请';
                case '出差成果审核';
                    $info = query('bussiness_trip', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['startTime'],
                        'lineTwo' => '结束时间：' . $info['endTime'],
                        'lineThree' => '出差事由：' . $info['reason'],
                    ];
                    $url = '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $info['id'];
                    break;
                case '加班申请';
                case '加班成果审核';
                    $info = query('work_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '加班事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workInfo/workInfo?id=' . $info['id'];
                    break;
                case '费用申请';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '金额(' . static::$unit . ')：' . $info['money'],
                        'lineTwo' => '事由：' . $info['reason'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/feeApplyInfo/feeApplyInfo?id=' . $info['id'];
                    break;
                case '费用报销';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '报销类型：' . $info['type'],
                        'lineTwo' => '报销事由：' . $info['reason'],
                        'lineThree' => '报销金额(' . static::$unit . ')：' . $info['money'],
                    ];
                    $url = '/oa/pages/costInfo/costInfo?id=' . $info['id'];
                    break;
                case '付款申请';
                    $info = query('payment', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '付款事由：' . $info['reason'],
                        'lineTwo' => '付款金额(' . static::$unit . ')：' . $info['money'],
                        'lineThree' => '收款单位：' . $info['company'],
                    ];
                    $url = '/oa/pages/paymentInfo/paymentInfo?id=' . $info['id'];
                    break;
                default:
                    $description = [
                        'lineOne' => ' ',
                        'lineTwo' => ' ',
                        'lineThree' => ' ',
                    ];
                    $url = '';
                    break;
            }

            $data['result'][] = array(
                "id" => $array['id'],//ID
                'orderNo' => $array['orderNo'],
                "applicant" => $array['applicant'],
                "applicantId" => $array['applicantId'],
                'flowName' => $array['flowName'],
                "workFlow" => $array['workFlow'],//状态
                'targetId' => $array['targetId'],
                'time' => date('m/d', strtotime($array['time'])),
                'description' => $description,
                'url' => $url
            );
        }
        $data['page'] = $page['para'];
        $data['sql'] = $page['sql'];
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }

    /**
     * 已审批的
     */
    public function approveed()
    {
        //全等查询数组
        $equal = array(
            'applicantId' => $this->post('applicantId'),
            'flowName' => $this->post('flowName') == '全部' ? '' : $this->post('flowName'),
        );
        //初始化
        $and = " and flowName in ('" . implode("','", self::whiteField) . "')";
        $and .= " and id in (SELECT distinct typeId FROM backlog WHERE stid = '" . self::$stid . "' AND workFlow = '已完成') ";
        if ($this->post('keyword')) {
            $and .= " and (flowName like '%" . $this->post('keyword') . "%' or orderNo like '%" . $this->post('keyword') . "%')";
        }
        $commitTime = $this->post('commit_time');
        if (!$commitTime) {
            if ($this->post('startDate')) {
                $commitTime = $this->post('startDate');
            }
            if ($this->post('endDate')) {
                $commitTime .= empty($commitTime) ? $this->post('endDate') : ('~' . $this->post('endDate'));
            }
        }
        if ($commitTime) {
            $and .= self::miniTimeComparison($commitTime, 'date', 'commitTime');
        }
        //获取查询结果
        $where = search(array("=" => $equal)) . $and;
        $page = $this->page(array("table" => 'audit', "where" => $where, "order" => "commitTime desc"));
        //数据分析
        $data['result'] = [];
        foreach ($page['array'] as $array) {
            switch ($array['flowName']) {
                case '补卡申请';
                    $info = query('work_sign_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '补卡时间点：' . $info['signTime'],
                        'lineTwo' => '补卡事由：' . $info['text'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/workSignAddInfo/workSignAdInfo?id=' . $info['id'];
                    break;
                case '请假申请';
                    $info = query('work_holiday', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '分类：' . $info['type'],
                        'lineTwo' => '开始时间：' . $info['startTime'],
                        'lineThree' => '结束时间：' . $info['endTime'],
                    ];
                    $url = '/oa/pages/workHolidayInfo/workHolidayInfo?id=' . $info['id'];
                    break;
                case '外出申请';
                case '外出成果审核';
                    $info = query('work_out', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '外出事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workOutInfo/workOutInfo?id=' . $info['id'];
                    break;
                case '加班申请';
                case '加班成果审核';
                    $info = query('work_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '加班事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workInfo/workInfo?id=' . $info['id'];
                    break;
                case '出差申请';
                case '出差成果审核';
                    $info = query('bussiness_trip', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['startTime'],
                        'lineTwo' => '结束时间：' . $info['endTime'],
                        'lineThree' => '出差事由：' . $info['reason'],
                    ];
                    $url = '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $info['id'];
                    break;
                case '费用申请';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '金额(' . static::$unit . ')：' . $info['money'],
                        'lineTwo' => '事由：' . $info['reason'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/feeApplyInfo/feeApplyInfo?id=' . $info['id'];
                    break;
                case '费用报销';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '报销类型：' . $info['type'],
                        'lineTwo' => '报销事由：' . $info['reason'],
                        'lineThree' => '报销金额(' . static::$unit . ')：' . $info['money'],
                    ];
                    $url = '/oa/pages/costInfo/costInfo?id=' . $info['id'];
                    break;
                case '付款申请';
                    $info = query('payment', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '付款事由：' . $info['reason'],
                        'lineTwo' => '付款金额(' . static::$unit . ')：' . $info['money'],
                        'lineThree' => '收款单位：' . $info['company'],
                    ];
                    $url = '/oa/pages/paymentInfo/paymentInfo?id=' . $info['id'];
                    break;
                default:
                    $description = [
                        'lineOne' => ' ',
                        'lineTwo' => ' ',
                        'lineThree' => ' ',
                    ];
                    $url = '';
                    break;
            }

            $data['result'][] = array(
                "id" => $array['id'],//ID
                'orderNo' => $array['orderNo'],
                "applicant" => $array['applicant'],
                "applicantId" => $array['applicantId'],
                'flowName' => $array['flowName'],
                "workFlow" => $array['workFlow'],//状态
                'targetId' => $array['targetId'],
                'time' => date('m/d', strtotime($array['time'])),
                'description' => $description,
                'url' => $url
            );
        }
        $data['page'] = $page['para'];
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }

    /**
     * 抄送给我的
     */
    public function copyMe()
    {

        //全等查询数组
        $equal = array(
            'applicantId' => $this->post('applicantId'),
            'flowName' => $this->post('flowName') == '全部' ? '' : $this->post('flowName'),
        );
        //初始化
        $and = " and flowName in ('" . implode("','", self::whiteField) . "')";
        $and .= " and id in (SELECT distinct typeId FROM message WHERE stid = '" . self::$stid . "') ";
        if ($this->post('keyword')) {
            $and .= " and (flowName like '%" . $this->post('keyword') . "%' or orderNo like '%" . $this->post('keyword') . "%')";
        }
        $commitTime = $this->post('commit_time');
        if (!$commitTime) {
            if ($this->post('startDate')) {
                $commitTime = $this->post('startDate');
            }
            if ($this->post('endDate')) {
                $commitTime .= empty($commitTime) ? $this->post('endDate') : ('~' . $this->post('endDate'));
            }
        }
        if ($commitTime) {
            $and .= self::miniTimeComparison($commitTime, 'date', 'commitTime');
        }
        //获取查询结果
        $where = search(array("=" => $equal)) . $and;
        $page = $this->page(array("table" => 'audit', "where" => $where, "order" => "commitTime desc"));
        //数据分析
        $data['result'] = [];
        foreach ($page['array'] as $array) {
            switch ($array['flowName']) {
                case '补卡申请';
                    $info = query('work_sign_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '补卡时间点：' . $info['signTime'],
                        'lineTwo' => '补卡事由：' . $info['text'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/workSignAddInfo/workSignAdInfo?id=' . $info['id'];
                    break;
                case '请假申请';
                    $info = query('work_holiday', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '分类：' . $info['type'],
                        'lineTwo' => '开始时间：' . $info['startTime'],
                        'lineThree' => '结束时间：' . $info['endTime'],
                    ];
                    $url = '/oa/pages/workHolidayInfo/workHolidayInfo?id=' . $info['id'];
                    break;
                case '外出申请';
                case '外出成果审核';
                    $info = query('work_out', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '外出事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workOutInfo/workOutInfo?id=' . $info['id'];
                    break;
                case '出差申请';
                case '出差成果审核';
                    $info = query('bussiness_trip', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['startTime'],
                        'lineTwo' => '结束时间：' . $info['endTime'],
                        'lineThree' => '出差事由：' . $info['reason'],
                    ];
                    $url = '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $info['id'];
                    break;
                case '加班申请';
                case '加班成果审核';
                    $info = query('work_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '加班事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workInfo/workInfo?id=' . $info['id'];
                    break;
                case '费用申请';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '金额(' . static::$unit . ')：' . $info['money'],
                        'lineTwo' => '事由：' . $info['reason'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/feeApplyInfo/feeApplyInfo?id=' . $info['id'];
                    break;
                case '费用报销';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '报销类型：' . $info['type'],
                        'lineTwo' => '报销事由：' . $info['reason'],
                        'lineThree' => '报销金额(' . static::$unit . ')：' . $info['money'],
                    ];
                    $url = '/oa/pages/costInfo/costInfo?id=' . $info['id'];
                    break;
                case '付款申请';
                    $info = query('payment', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '付款事由：' . $info['reason'],
                        'lineTwo' => '付款金额(' . static::$unit . ')：' . $info['money'],
                        'lineThree' => '收款单位：' . $info['company'],
                    ];
                    $url = '/oa/pages/paymentInfo/paymentInfo?id=' . $info['id'];
                    break;
                default:
                    $description = [
                        'lineOne' => ' ',
                        'lineTwo' => ' ',
                        'lineThree' => ' ',
                    ];
                    $url = '';
                    break;
            }

            $data['result'][] = array(
                "id" => $array['id'],//ID
                'orderNo' => $array['orderNo'],
                "applicant" => $array['applicant'],
                "applicantId" => $array['applicantId'],
                'flowName' => $array['flowName'],
                "workFlow" => $array['workFlow'],//状态
                'targetId' => $array['targetId'],
                'time' => date('m/d', strtotime($array['time'])),
                'description' => $description,
                'url' => $url
            );
        }
        $data['page'] = $page['para'];
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }

    /**
     * 我发起的
     */
    public function myApply()
    {
        //全等查询数组
        $equal = array(
            'applicantId' => self::$stid,
            'workFlow' => $this->post('search_state'),
            'flowName' => $this->post('flowName') == '全部' ? '' : $this->post('flowName'),
        );
        //初始化
        $and = " and flowName in ('" . implode("','", self::whiteField) . "')";
        if ($this->post('keyword')) {
            $and .= " and (flowName like '%" . $this->post('keyword') . "%' or orderNo like '%" . $this->post('keyword') . "%')";
        }
        $commitTime = $this->post('commit_time');
        if (!$commitTime) {
            if ($this->post('startDate')) {
                $commitTime = $this->post('startDate');
            }
            if ($this->post('endDate')) {
                $commitTime .= empty($commitTime) ? $this->post('endDate') : ('~' . $this->post('endDate'));
            }
        }
        if ($commitTime) {
            $and .= self::miniTimeComparison($commitTime, 'date', 'commitTime');
        }
        //获取查询结果
        $where = search(array("=" => $equal)) . $and;
        $page = $this->page(array("table" => 'audit', "where" => $where, "order" => "commitTime desc"));

        //数据分析
        $data['result'] = [];
        foreach ($page['array'] as $array) {
            switch ($array['flowName']) {
                case '补卡申请';
                    $info = query('work_sign_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '补卡时间点：' . $info['signTime'],
                        'lineTwo' => '补卡事由：' . $info['text'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/workSignAddInfo/workSignAdInfo?id=' . $info['id'];
                    break;
                case '请假申请';
                    $info = query('work_holiday', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '分类：' . $info['type'],
                        'lineTwo' => '开始时间：' . $info['startTime'],
                        'lineThree' => '结束时间：' . $info['endTime'],
                    ];
                    $url = '/oa/pages/workHolidayInfo/workHolidayInfo?id=' . $info['id'];
                    break;
                case '外出申请';
                case '外出成果审核';
                    $info = query('work_out', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '外出事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workOutInfo/workOutInfo?id=' . $info['id'];
                    break;
                case '出差申请';
                case '出差成果审核';
                    $info = query('bussiness_trip', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['startTime'],
                        'lineTwo' => '结束时间：' . $info['endTime'],
                        'lineThree' => '出差事由：' . $info['reason'],
                    ];
                    $url = '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $info['id'];
                    break;
                case '加班申请';
                case '加班成果审核';
                    $info = query('work_add', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '开始时间：' . $info['expectTimeStart'],
                        'lineTwo' => '结束时间：' . $info['expectTimeEnd'],
                        'lineThree' => '加班事由：' . $info['text'],
                    ];
                    $url = '/oa/pages/workInfo/workInfo?id=' . $info['id'];
                    break;
                case '费用申请';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '金额(' . static::$unit . ')：' . $info['money'],
                        'lineTwo' => '事由：' . $info['reason'],
                        'lineThree' => ' ',
                    ];
                    $url = '/oa/pages/feeApplyInfo/feeApplyInfo?id=' . $info['id'];
                    break;
                case '费用报销';
                    $info = query('cost', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '报销类型：' . $info['type'],
                        'lineTwo' => '报销事由：' . $info['reason'],
                        'lineThree' => '报销金额(' . static::$unit . ')：' . $info['money'],
                    ];
                    $url = '/oa/pages/costInfo/costInfo?id=' . $info['id'];
                    break;
                case '付款申请';
                    $info = query('payment', "id = '$array[targetId]'");
                    $description = [
                        'lineOne' => '付款事由：' . $info['reason'],
                        'lineTwo' => '付款金额(' . static::$unit . ')：' . $info['money'],
                        'lineThree' => '收款单位：' . $info['company'],
                    ];
                    $url = '/oa/pages/paymentInfo/paymentInfo?id=' . $info['id'];
                    break;
                default:
                    $description = [
                        'lineOne' => ' ',
                        'lineTwo' => ' ',
                        'lineThree' => ' ',
                    ];
                    $url = '';
                    break;
            }

            $data['result'][] = array(
                "id" => $array['id'],//ID
                'orderNo' => $array['orderNo'],
                "applicant" => $array['applicant'],
                "applicantId" => $array['applicantId'],
                'flowName' => $array['flowName'],
                "workFlow" => $array['workFlow'],//状态
                'targetId' => $array['targetId'],
                'time' => date('m/d', strtotime($array['time'])),
                'description' => $description,
                'url' => $url
            );
        }
        $data['page'] = $page['para'];
        $data['sql'] = $page['sql'];
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }


    /*
     * 获取加密参数
     */
    public function getPara()
    {
        $flowName = $this->post('flowName');
        $id = $this->post('id');
        $act = $this->post('act');
        $commitBeforeFun = $commitAfterFun = $auditBeforFun = $auditAfterFun = $cancelFun = '';
        switch ($flowName) {
            case '费用报销':
                $targetCla = 'cost';
                $cla = 'costApp';
                $table = 'cost';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            case '补卡申请':
                $targetCla = 'workSignAdd';
                $cla = 'workSignAddApp';
                $table = 'work_sign_add';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                $commitBeforeFun = 'prepare';
                $auditAfterFun = 'finish';
                $cancelFun = "cancelFun";
                break;
            case '请假申请':
                $targetCla = 'work';
                $cla = 'workApp';
                $table = 'work_holiday';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            case '加班申请':

            case '加班成果审核':
                $targetCla = 'workAdd';
                $cla = 'workAddApp';
                $table = 'work_add';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            case '出差申请':

            case '出差成果审核':
                $targetCla = 'bussinessTrip';
                $cla = 'bussinessTripApp';
                $table = 'bussiness_trip';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            case '外出申请':

            case '外出成果审核':
                $targetCla = 'workOut';
                $cla = 'workOutApp';
                $table = 'work_out';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                if($flowName == '外出成果审核' && empty($info['result'])){
                    $this->resp['warn'] = '请填写外出成果';
                }
                break;
            case '费用申请':
                $targetCla = 'feeApply';
                $cla = 'feeApplyApp';
                $table = 'cost';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            case '付款申请':
                $targetCla = 'payment';
                $cla = 'paymentApp';
                $table = 'payment';
                $info = query($table, "id = '$id'");
                $state = $info['state'];//当前状态
                if (empty($info['id'])) {
                    $this->resp['warn'] = '未找到此' . $flowName;
                }
                break;
            default:
                $this->resp['warn'] = '未找到审批流程';
                $cla = '';
                $table = '';
                $state = '';
                $targetCla = '';
                break;
        }
        $data = [];
        if (empty($this->resp['warn'])) {
            $achivmentState = ['外出成果审核', '加班成果审核', '出差成果审核'];
            $this->code = 1;
            if ($act == 'start') {
                //提交
                $commitState = '';
                if (in_array($flowName, $achivmentState)) {
                    $commitState = '审核成果';
                }
                $data = self::encryptDecrypt(json_encode([
                    'name' => $flowName,
                    'table' => $table,
                    'process' => [
                        'state' => $commitState,
                        // 预览函数
                        'detail' => [
                            'cla' => $targetCla,
                            'fun' => 'detail'
                        ],
                        //执行发起时验证函数
                        'before' => [
                            'cla' => $cla,
                            'fun' => $commitBeforeFun,
                            'data' => ['id' => $id]
                        ],
                        //完成发起后执行函数
                        'after' => [
                            'cla' => $cla,
                            'fun' => $commitAfterFun,
                            'data' => ['id' => $id]
                        ],
                    ],
                ], 320));
            } elseif ($act == 'audit') {
                //审批
                $changeState = ['草稿', '已通过'];
                if (in_array($flowName, $achivmentState)) {
                    $changeState = ['已通过', '成果确认'];
                }
                $data = self::encryptDecrypt(json_encode([
                    'name' => $flowName,
                    'table' => $table,
                    // 当前状态
                    'state' => $state,
                    // 变更
                    'field' => ['state'],   //变更字段 可多个
                    'value' => [
                        'state' => $changeState,
                    ],
                    // 审核时回调
                    'process' => [
                        //执行首次审核时验证
                        'before' => [
                            'cla' => $cla,
                            'fun' => $auditBeforFun,
                            'data' => ['id' => $id]
                        ],
                        //执行末次审核后处理
                        'after' => [
                            'cla' => $cla,
                            'fun' => $auditAfterFun,
                            'data' => ['id' => $id]
                        ],
                    ],
                ], 320));
            } elseif ($act == 'cancel') {
                //撤销审批
                $data = self::encryptDecrypt(json_encode([
                    'name' => $flowName,
                    'table' => $table,
                    // 当前状态
                    'state' => $state,
                    // 变更
                    'field' => ['state'],   //变更字段 可多个
                    'value' => [
                        'state' => ['草稿'],
                    ],
                    'process' => [
                        //完成发起后执行函数
                        'after' => [
                            'cla' => $cla,
                            'fun' => $cancelFun,
                            'data' => ['id' => $id]
                        ],
                    ],
                ], 320));
            } else {
                $data = self::encryptDecrypt(json_encode([
                    'name' => $flowName,
                    'table' => $table,
                ], 320));
            }
        }
        $this->resp['data']['result'] = $data;
    }

    /**
     * 判断审批流程中是否有审批人自选
     * @param $flow
     * @return bool
     */
    public static function judgeSelfChoose($flow): bool
    {
        $bool = false;
        foreach ($flow as $array) {
            if ($array['type'] == '审批人自选' && $array['form'] == 'approver' && $array['state'] == '审核中') {
                $bool = true;
                break;
            } elseif ($array['form'] == 'approver' && $array['state'] == '审核中') {
                break;
            }
        }
        return $bool;
    }


    /**
     *
     * 审批中转
     *
     */
    public function operate()
    {
        $act = $this->post('act');
        $id = $this->post('id');
        $body = $this->post('body');
        $warn = '';
        $data['auditType'] = '';
        switch ($act) {
            // 撤销审批
            case 'cancel':
                $body = self::validateBody($body, 'cancel');
                $warn = (!is_array($body)) ? $body : self::cancel($id, $body);
                break;
            // 发起审批
            case 'start':
                $body = self::validateBody($body);
                $flow = (!is_array($body)) ? $body : self::findFlow($id, $body);
                if (!is_array($flow)) {
                    $warn = $flow;
                } else {
                    //先判断流程中是否有审批人自选，有则选人
                    $result = self::judgeSelfChoose($flow);
                    if ($result === true) {
                        $this->code = 1;
                        $data['auditType'] = '审批人自选';
                    } else {
                        $warn = self::start($id, $body, $flow) === true ? 2 : '发起审批失败';
                    }
                }
                break;
            // 添加审批人
            case 'addApprover':
                $body = self::validateBody($body);
                if ((!is_array($body))) {
                    $warn = $body;
                } else {
                    $warn = $this->insertBeforeEdit();
                }
                break;
            // 转交审批人
            case 'transfer':
                $body = self::validateBody($body);
                if ((!is_array($body))) {
                    $warn = $body;
                } else {
                    $warn = $this->transferLayerEdit();
                }
                break;
            // 催办
            case 'press':
                $warn = $this->press();
                break;
            default:
                $warn = '未知操作';
                break;
        }

        if (!self::isNull($warn)) {
            if (str_contains($warn, '成功')) {
                $this->code = 1;
                $this->resp['warn'] = $warn;
            } elseif ($warn == 2) {
                $this->code = 1;
            }
        }
        resp:
        $this->resp['warn'] = $warn;
        $this->resp['data'] = $data;
    }

    /**
     * 催办
     *
     * @param string $id
     * @return string
     */
    public function press(): string
    {
        $id = $this->post('id');
        $flowName = $this->post('flowName');
        $where = '';
        if ($flowName) {
            $where = " and flowName = '$flowName'";
        }
        $audit = query('audit', " targetId = '$id'" . $where);
        if (!$audit['id']) {
            return '审批记录不存在';
        } else {
            $approver = explode(',', $audit['approverId']);
            // 审批人列表
            $approverArr = self::filterArray($approver);
            foreach ($approverArr as $stid) {
                static::update([
                    'table' => 'backlog',
                    'field' => [
                        'urging' => '是',
                        'time' => $this->time,
                    ],
                    'where' => " stid = '$stid'  AND typeId = '$audit[id]' AND workFlow = '待处理' ;",
                ]);
            }
            return '催办成功';
        }
    }

    /**
     * 执行审批
     *
     * @param string $id 时间id
     * @param array $body body
     * @param array $array 审批流程
     */
    public static function launch(string $id, array $body, array $array)
    {
        // 执行发起时验证函数
        $process = $body['process']['before'];
        if (is_array($process) && !empty($process) && !empty($process['fun'])) {
            $warn = self::call($process['cla'], $process['fun'], $process['data']);
            if ($warn !== true) {
                return $warn;
            }
        }
        $flag = false;//判断是否有审批节点
        $auto = false;
        foreach ($array as $item) {
            if ($item['form'] == 'approver') {
                $flag = true;
                if (isset($item['isAuto']) && $item['isAuto'] == '否') {
                    $auto = true;
                }
            }
        }
        if (!$flag) {
            return '此审批流程中没有审批节点';
        }
        if (!$auto) {
            return '暂不能设置全自动审批流程，需要其中一个节点为非自动审批状态';
        }
        // 查找审批人
        $approver = self::findAuditPeople($array);
        $warn = static::update([
            'table' => $body['table'],
            'field' => [
                'examine' => json_encode($approver['flow'], 320),
                'state' => isset($body['process']['state']) && $body['process']['state'] ? $body['process']['state'] : '审核中',
                'updateTime' => date('Y-m-d H:i:s')
            ],
            'where' => " id = '$id' ",
        ]);
        if ($warn != '更新成功') {
            return $warn;
        } else {
            $applicantDepartment = self::findStaffDepartment(self::$stid);
            $field = [
                'orderNo' => query($body['table'], " id = '$id' ")['orderNo'],
                'flowName' => $body['name'],
                'targetId' => $id,
                'targetCla' => $body['process']['detail']['cla'],
                'targetFun' => $body['process']['detail']['fun'],
            ];
            $audit = query('audit', generateWhere($field));
            if (empty($audit['id'])) {
                // 写入审批表
                $auditId = self::getNo();
                static::insert([
                    'table' => 'audit',
                    'field' => array_merge($field, [
                        'id' => $auditId,
                        'applicant' => self::findStaff(self::$stid),
                        'applicantId' => self::$stid,
                        'applicantDepartment' => $applicantDepartment,
                        'commitTime' => date('Y-m-d H:i:s'),
                        'workFlow' => '审核中',
                        'approver' => implode(',', $approver['staffName']),
                        'approverId' => implode(',', $approver['staffId']),
                        'time' => date('Y-m-d H:i:s'),
                    ])
                ]);
            } else {
                $auditId = $audit['id'];
                static::update([
                    'table' => 'audit',
                    'field' => [
                        'workFlow' => '审核中',
                        'approver' => implode(',', $approver['staffName']),
                        'approverId' => implode(',', $approver['staffId']),
                    ],
                    'where' => generateWhere($field)
                ]);
            }
            // 审批人自选时，不发送待办
            $text = "【{$applicantDepartment}】-【" . self::findStaff(self::$stid) . "】提交的【{$body['name']}】需要您审批";
            self::sendTip($approver['staffId'], $auditId, $text);
            self::findAutoNode($approver['flow'], $audit['flowName'], $audit['id'], "【{$applicantDepartment}】-【" . self::findStaff(self::$stid) . "】提交的【{$body['name']}】需要您审批");
            // 执行抄送
            $copyStaff = self::findCopy($approver['flow'], $id, $body['table']);
            self::batchMessage($copyStaff, $auditId, "您有一条【{$applicantDepartment}】-【" . self::findStaff(self::$stid) . "】提交的【{$body['name']}】抄送待查看");
            return true;
        }
    }

    /**
     * 找抄送人
     * @param array $flow 审批流程
     * @param $targetId
     * @param $table
     * @return array
     */
    public static function findCopy(array $flow, $targetId, $table): array
    {
        $copyStaff = [];//抄送人；
        foreach ($flow as $k => $array) {
            if ($array['form'] == 'approver') {
                if ($array['state'] == '审核中') {
                    break;
                } else {
                    //已通过
                    $copyStaff = [];
                }
            }
            if ($array['form'] == 'notifier') {
                //抄送
                $copyPeople = explode(';', $array['staff[]']);
                $copyStaff = array_merge($copyStaff, $copyPeople);
                $copyStaff = array_unique(array_filter($copyStaff));
                foreach ($copyStaff as $stid) {
//                    $array['stateNode'][$stid] = '已抄送';
                    $array['stateNode'] = self::updateStateNode($array['stateNode'], '已抄送', $stid);
                }
                $array['state'] = '已抄送';
            }
            $flow[$k] = $array;
        }
        update(array('table' => $table, 'field' => ['examine' => json_encode($flow, 320)], 'where' => " id = '$targetId'"));
        return array_unique($copyStaff);
    }

    /**
     * 发起审批
     *
     * @param $id
     * @param $body
     * @param $node
     * @return string|bool
     */
    private static function start($id, $body, $node): bool|string
    {
        // 执行发起操作
        $warn = self::launch($id, $body, $node);
        if ($warn === true) {
            // 完成发起后执行函数
            $process = $body['process']['after'];
            if (is_array($process) && !empty($process)) {
                $process['data'] = $process['data'] ?? [];
                self::call($process['cla'], $process['fun'], $process['data']);
            }
        }
        return $warn;
    }


    /**
     * 验证参数
     *
     * @param string $body
     * @return string|array
     */
    private static function validateBody(string $body, $type = ''): array|string
    {
        $warn = '';
        if (self::isNull($body)) {
            $warn = "body 参数不能为空";
        } else {
            $body = json_decode(self::encryptDecrypt($body, true), true);
            if (!is_array($body)) {
                $warn = "body 参数格式错误";
            } else {
                $field = ['table' => $body['table']];
                $annotation = ['table' => '调整对象'];
                $rules = ['table' => 'required'];
                switch ($type) {
                    // 撤销审批
                    case 'cancel':
                        // 审批
                    case 'approval':
                        $field = array_merge($field, [
                            'state' => $body['state'],
                            'field' => $body['field'],
                            'value' => $body['value'],
                            'process' => $body['process'],
                        ]);
                        $annotation = array_merge($annotation, [
                            'state' => '当前状态',
                            'field' => '调整字段',
                            'value' => '调整值',
                            'process' => '处理类型',
                        ]);
                        $rules = array_merge($rules, [
                            'state' => 'required',
                            'field' => 'required',
                            'value' => 'required',
                        ]);
                        break;
                }
                // 校验是否符合规则
                $vt = new verify();
                $result = $vt->setAliases($annotation)->validate($field, $rules)->isOk();
                if ($result === false) {
                    $warn = $vt->getErrs()[0];  // 多个规则提示最前面一条
                }
            }
        }
        return self::isNull($warn) ? $body : $warn;
    }

    /**
     * 更新状态节点
     */
    public static function updateStateNode($node, $state, $stid, $insert = false): array
    {
        $isExist = false;
        foreach ($node as $k => $item) {
            if ($item['stid'] == $stid) {
                $isExist = true;
                $node[$k]['state'] = $state;
                break;
            }
        }
        if ($insert && !$isExist) {
            //判断当前是否已存在此人
            $node[] = [
                'stid' => $stid,
                'state' => $state,
            ];
        }
        return $node;
    }


    /**
     * 获取状态一维数组
     */
    public static function returnStateCollection($array): array
    {
        return array_column(array_filter($array, function ($val) {
            return $val;
        }), 'state');
    }

    /**
     * 获取员工ID一维数组
     */
    public static function returnStidCollection($array): array
    {
        return array_column(array_filter($array, function ($val) {
            return $val;
        }), 'stid');
    }


    /**
     * 获取已审核过的记录
     */
    public function getAuditPassRecord(){
        $id = $this->post('id');//对应表ID
        $body = self::validateBody($this->post('body'));
        $info = query($body['table'], " id = '$id'");
        $examine = (array)json_decode($info['examine'], true);
        $data['list'][] = [
            'id'=>'start',
            'title'=>'1 发起',
            'index'=>1
        ];
        $index=1;
        foreach ($examine as $array) {
            if ($array['form'] == 'approver' && $array['state'] == '已通过') {
                //已审核过的节点
                $index++;
                $text = $array['type'] . '-' . $array['multiType'];
                $stidArr = [];
                foreach ($array['stateNode'] as $stateNode) {
                    if ($stateNode['state'] == '已通过') {
                        $stidArr[] = self::findStaff($stateNode['stid']);
                    }
                }
                if (count($stidArr) > 0) {
                    $text .= "-" . implode(',', $stidArr);
                }
                $data['list'][] = [
                    'id'=>$array['id'],
                    'title'=>$index.' '.$text,
                    'index'=>$index
                ];
            }
        }
        //返回
        $this->code = 1;
        $this->resp['data'] = $data;
    }
    /**
     * 审核编辑
     */
    public function auditLayerEdit()
    {
        $flowId = $this->post('flowId');//审核节点ID
        $id = $this->post('id');//对应表ID
        $text = $this->post('text');//备注
        $state = $this->post('state');//审批状态
        $body = $this->post('body');
        $body = self::validateBody($body);
        $targetInfo = query($body['table'], " id = '$id'");
        $where = self::flowWhere($body['name'] ?? '', $targetInfo['orderNo'] ?? '');
        $audit = query('audit', " targetId = '$id' $where order by updateTime desc");
        if (empty($audit['id'])) {
            $this->resp['warn'] = '未找到此审批记录';
        } elseif ($audit['workFlow'] != '审核中') {
            $this->resp['warn'] = '此记录不是审核中状态';
        } elseif (!in_array(self::$stid, explode(',', $audit['approverId']))) {
            $this->resp['warn'] = '您不是当前审核人，不能审核此记录';
        } elseif (empty($this->post('body'))) {
            $this->resp['warn'] = '未找到请求参数';
        } elseif (empty($state) || !in_array($state, ['通过', '驳回'])) {
            $this->resp['warn'] = '未找到审批结果';
        } else {
            $targetInfo = query($body['table'], " id = '$id'");
            $flow = json_decode($targetInfo['examine'], true);
            if (!is_array($flow) || empty($flow)) {
                $this->resp['warn'] = '未找到审批流程';
            } elseif ($state == '驳回') {
                foreach ($flow as $k => $array) {
                    if ($array['state'] == '审核中' && $array['form'] == 'approver') {
                        $approver = explode(';', $array['staff[]']);
                        if (!in_array(self::$stid, (array)$approver)) {
                            $this->resp['warn'] = '您已审批过了，请勿重复操作!';
                            goto resp;
                        }
                        $array['stateNode'] = self::updateStateNode($array['stateNode'], '已驳回', self::$stid);
                        $array['auditFollow'][self::$stid] = $text;
                        $array['state'] = '已驳回';
                        $flow[$k] = $array;
                        break;
                    }
                }

                $field = [
                    'examine' => json_encode($flow, 320),
                ];
                $field['examine'] = addcslashes($field['examine'],'\\');
                if (empty($flowId) || !str_contains($field['examine'], $flowId)) {
                    $flowId = 'start';//如果未找到此ID,则默认驳回到发起人
                }
                if ($flowId == 'start') {
                    if (is_array($body['field'])) {
                        foreach ($body['field'] as $item) {
                            $field[$item] = $body['value'][$item][0];
                        }
                    }
                    //驳回
                    $this->resp['warn'] = update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                    if ($this->resp['warn'] == '更新成功') {
                        //更新待办
                        backlogEnd(array(
                            "stid" => $this->control['stid'],
                            "typeId" => $audit['id'],
                        ));
                        //清楚未处理的待办
                        $this->clearBackLog($audit['id']);
                        //给发起人发送消息
                        message(array(
                            "stid" => $audit['applicantId'],
                            "type" => $audit['flowName'],
                            "typeId" => $audit['id'],
                            "text" => "您提交的【{$audit['flowName']}】已被驳回" . ($text ? '，驳回原因：' . $text : ''),
                        ));
                        //添加审批记录
                        auditingFollow([
                            "type" => $audit['flowName'],
                            "typeId" => $audit['id'],
                            "text" => "【{$this->control['name']}】驳回了【{$audit['flowName']}】" . ($text ? '，备注：' . $text : '') . "【小程序】",
                            'remark' => $text,
                            'source' => 'applet',
                            'staffName' => $this->control['name'],
                            'job' => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name']
                        ]);
                        //更新审批表
                        update(array('table' => 'audit', 'field' => ['workFlow' => '草稿', 'approver' => '', 'approverId' => '', 'commitTimePrevious' => '', 'commitTime' => ''], 'where' => " id = '$audit[id]'"));
                        $this->code = 1;
                        $this->resp['warn'] = '驳回成功';
                    }
                }else{
                    //驳回到指定审核节点
                    $afterFlag = false;
                    foreach ($flow as $k => $array) {
                        if ($array['form'] =='approver' && ($flowId == $array['id'] || $afterFlag)) {
                            $afterFlag = true;
                            $array['state'] = '审核中';
                            unset($array['auditFollow']);
                            foreach ($array['stateNode'] as $index => $item) {
                                $array['stateNode'][$index]['state'] = '审核中';
                            }
                        }
                        $flow[$k] = $array;
                    }
                    $field = [
                        'examine' => json_encode($flow, 320),
                    ];
                    $json['warn'] = update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                    if ($json['warn'] == '更新成功') {
                        $this->rejectTheNode($flow, $audit, $text);
                        $this->code = 1;
                        $this->resp['warn'] = '驳回成功';
                    }
                }

            } else {
                //通过
                //寻找审批顺序
                $auditOrderBy = $this->findAuditOrder($flow);
                $nowAuditType = '';//当前审批类型
                foreach ($flow as $k => $array) {
                    if ($array['state'] == '审核中' && $array['form'] == 'approver') {
                        $approver = explode(';', $array['staff[]']);
                        if (!in_array(self::$stid, (array)$approver)) {
                            $this->resp['warn'] = '您已审批过了，请勿重复操作!';
                            goto resp;
                        }
                        $nowAuditType = $array['multiType'];
//                        $array['stateNode'][self::$stid] = '已通过';
                        $array['stateNode'] = self::updateStateNode($array['stateNode'], '已通过', self::$stid);
                        $array['auditFollow'][self::$stid] = $text;
                        if ($array['multiType'] == '或签') {
                            $array['state'] = '已通过';
                        } elseif (in_array($array['multiType'], ['会签', '依次审批'])) {
                            if (!in_array('审核中', self::returnStateCollection($array['stateNode']))) {
                                //全部已通过
                                $array['state'] = '已通过';
                            } else {
                                $array['state'] = '审核中';
                            }
                        }
                        $flow[$k] = $array;
                        break;
                    }
                }


                $result = self::findAuditPeople($flow);
                $field = [
                    'examine' => json_encode($result['flow'], 320),
                ];
                $field['examine'] = addcslashes($field['examine'],'\\');
                if ($result['isEnd']) {
                    $field['passTime'] = $this->time;
                    //更新状态
                    if (is_array($body['field'])) {
                        foreach ($body['field'] as $item) {
                            $field[$item] = $body['value'][$item][1];
                        }
                    }
                }

                $this->resp['warn'] = static::update(array('table' => $body['table'], 'field' => $field, 'where' => " id = '$id'"));
                if ($this->resp['warn'] == '更新成功') {
                    //更新当前审批人的待办
                    backlogEnd(array(
                        "stid" => $this->control['stid'],
                        "typeId" => $audit['id'],
                    ));

                    if ($nowAuditType == '或签') {
                        //清除其他或签人的待办事项
                        $auditStaff = explode(',', $audit['approverId']);
                        foreach ($auditStaff as $stid) {
                            if ($stid != $this->control['stid'] && $stid) {
                                delete(array('table' => 'backlog', 'where' => "typeId = '$audit[id]' and stid = '$stid' and workFlow = '待处理'"));
                            }
                        }
                    }
                    //添加审批记录
                    auditingFollow([
                        "type" => $audit['flowName'],
                        "typeId" => $audit['id'],
                        "text" => "【{$this->control['name']}】通过了【{$audit['flowName']}】" . ($text ? '，备注：' . $text : '') . "【小程序】",
                        'remark' => $text,
                        'source' => 'applet',
                        'staffName' => $this->control['name'],
                        'job' => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name']
                    ]);
                    if ($auditOrderBy['auditNode'] == 1 && $auditOrderBy['staffNode'] == 1) {
                        //第一次审批
                        self::call($body['process']['before']['cla'], $body['process']['before']['fun'], $body['process']['before']['data'] ?? []);
                    }
                    if ($result['nodeIsEnd']) {
                        //当前节点完成
                        //判断是否有抄送人，发送消息
                        $copyStaff = self::findCopy($result['flow'], $id, $body['table']);
                        self::batchMessage($copyStaff, $audit['id'], "您有一条【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】抄送待查看");
                    }
                    if ($result['isEnd']) {
                        //当前是最后一次审批
                        //审核完成调用方法
                        self::call($body['process']['after']['cla'], $body['process']['after']['fun'], $body['process']['after']['data'] ?? []);
                        //给发起人发送已完成的消息
                        message(array(
                            "stid" => $audit['applicantId'],
                            "type" => $audit['flowName'],
                            "typeId" => $audit['id'],
                            "text" => "您提交的【{$audit['flowName']}】已通过",
                        ));
                    } elseif ($result['auditType'] == '审批人自选') {
                        self::batchMessage([$audit['applicantId']], $audit['id'], "您的【{$audit['flowName']}】需要选择审批人");
                    } else {
                        //给下一审批人添加待办
                        self::sendTip($result['staffId'], $audit['id'], "【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                        self::findAutoNode($result['flow'], $audit['flowName'], $audit['id'], "【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                    }

                    //更新审批表
                    $field = [
                        'approver' => implode(',', $result['staffName']),
                        'workFlow' => $result['isEnd'] ? '已通过' : '审核中',
                        'approverId' => implode(',', $result['staffId'])
                    ];
                    if ($result['nodeIsEnd']) {
                        $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                    }
                    //更新审批表
                    update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
                    $this->code = 1;
                    $this->resp['warn'] = '审批成功';
                }
            }
        }
        resp:
    }


    /**
     * 寻找审批顺序
     */
    public function findAuditOrder($flow): array
    {
        $staffNode = 0;//当前审批节点第几次审批
        $auditNode = 0;//处于第几个审批节点
        foreach ($flow as $array) {
            if ($array['form'] == 'approver') {
                $auditNode++;
                if ($array['state'] == '审核中') {
                    if ($array['multiType'] == '或签') {
                        $staffNode++;
                    } elseif ($array['multiType'] == '依次审批') {
                        foreach ($array['stateNode'] as $item) {
                            $staffNode++;
                            if ($item['state'] == '审核中') {
                                break;
                            }
                        }
                    } elseif ($array['multiType'] == '会签') {
                        foreach ($array['stateNode'] as $item) {
                            if ($item['state'] == '审核中') {
                                $staffNode++;
                            }
                        }
                    }
                    break;
                }
            }
        }
        return ['auditNode' => $auditNode, 'staffNode' => $staffNode];
    }

    /**
     * 清除掉未处理的待办
     * @param string $id 我的审批表ID
     */
    public function clearBackLog(string $id)
    {
        delete(array('table' => 'backlog', 'where' => "typeId = '$id' and workFlow = '待处理'"));
    }

    /**
     * 审批人选择插入另一审批人
     */
    public function insertBeforeEdit(): string
    {
        $chooseStidArr = (array)json_decode($_POST['stid'], true);
        $id = $this->post('id');
        $body = $this->post('body');
        $body = self::validateBody($body);
        if (empty($chooseStidArr) || !is_array($chooseStidArr)) {
            return "请选择审核人";
        } else {
            $chooseStid = $chooseStidArr[0]['stid'];
            $table = $body['table'];
            $body['name'] = $body['name'] ?? '';
            $info = query($table, " id = '$id'");
            $where = self::flowWhere($body['name']);
            $audit = query('audit', " targetId = '$info[id]' {$where}");
            $flow = $info['examine'] ? json_decode($info['examine'], true) : [];
            foreach ($flow as $k => $array) {
                if ($array['form'] == 'approver' && $array['state'] == '审核中') {
                    //当前审批节点
                    $auditStaff = explode(';', $array['staff[]']);
                    $auditStaff = array_unique(array_filter($auditStaff));
                    if ($array['multiType'] == '依次审批') {
                        $newAuditStaff = [];
                        foreach ($auditStaff as $stid) {
                            if ($stid == self::$stid) {
                                $newAuditStaff[] = $chooseStid;
                                $newAuditStaff[] = $stid;
                            }
                            $newAuditStaff[] = $stid;
                        }
                        //插入后的审批人
                        $stateBox = [];
                        foreach ($newAuditStaff as $stid) {
//                            $array['stateNode'][$stid] = $array['stateNode'][$stid] ?? '审核中';
                            $stateBox = self::updateStateNode($stateBox, self::returnState($array['stateNode'], $stid) ?: '审核中', $stid, true);
                        }
                        $array['stateNode'] = $stateBox;
                        $array['staff[]'] = implode(';', $newAuditStaff);
                    } else {
                        $auditStaff[] = $chooseStid;
                        foreach ($auditStaff as $stid) {
//                            $array['stateNode'][$stid] = $array['stateNode'][$stid] ?? '审核中';
                            $array['stateNode'] = self::updateStateNode($array['stateNode'], self::returnState($array['stateNode'], $stid) ?: '审核中', $stid, true);
                        }
                        $array['staff[]'] = implode(';', $auditStaff);
                    }
                    $flow[$k] = $array;
                    break;
                }
            }

            //寻找下一审批人
            $result = self::findAuditPeople($flow);
            $field = [
                'examine' => json_encode($result['flow'], 320)
            ];

            $warn = update(array('table' => $table, 'field' => $field, 'where' => " id = '$info[id]'"));
            if ($warn == '更新成功') {
                $staff = query('staff', "stid = '$chooseStid'");
                //添加审批记录
                auditingFollow([
                    "type" => $audit['flowName'],
                    "typeId" => $audit['id'],
                    "text" => "【{$this->control['name']}】插入了新的审批人【{$staff['name']}】" . "【小程序】",
                    'remark' => '',
                    'source' => 'applet',
                    'staffName' => $this->control['name'],
                    'job' => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name']
                ]);
                //更新审批表
                $field = [
                    'approver' => implode(',', $result['staffName']),
                    'workFlow' => $result['isEnd'] ? '已通过' : '审核中',
                    'approverId' => implode(',', $result['staffId'])
                ];
                if ($result['nodeIsEnd']) {
                    $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                }

                $warn = update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
                if ($warn == '更新成功') {
                    //待办提醒
                    self::sendTip($result['staffId'], $audit['id'], "【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                }
                //更新待办
                backlogEnd(array(
                    "stid" => $this->control['stid'],
                    "typeId" => $audit['id'],
                ));
                $warn = '添加成功';
            }
        }
        return $warn;
    }

    /**
     * 获取当前审核人的审批状态
     */
    public static function returnState($array, $stid): string
    {
        foreach ($array as $item) {
            if ($stid == $item['stid']) {
                return $item['state'];
            }
        }
        return '';
    }

    /**
     * 转交提交
     */
    public function transferLayerEdit(): string
    {
        $chooseStidArr = (array)json_decode($_POST['stid'], true);
        $id = $this->post('id');
        $body = $this->post('body');
        $body = self::validateBody($body);
        if (empty($chooseStidArr) || !is_array($chooseStidArr)) {
            return "请选择转交人";
        } else {
            $chooseStid = $chooseStidArr[0]['stid'];
            $table = $body['table'];
            $info = query($table, " id = '$id'");
            $body['name'] = $body['name'] ?? '';
            $where = self::flowWhere($body['name']);
            $audit = query('audit', " targetId = '$info[id]' {$where}");
            $flow = $info['examine'] ? json_decode($info['examine'], true) : [];
            //寻找下一审批人
            $result = self::findAuditPeople($flow, '转交', $chooseStid);
            $field = [
                'examine' => json_encode($result['flow'], 320)
            ];
            if ($result['isEnd']) {
                if (is_array($body['field'])) {
                    foreach ($body['field'] as $item) {
                        $field[$item] = $body['value'][$item][0];
                    }
                }
            }
            $warn = update(array('table' => $table, 'field' => $field, 'where' => " id = '$info[id]'"));
            if ($warn == '更新成功') {
                if ($result['isEnd']) {
                    //审核完成调用方法
                    self::call($body['process']['after']['cla'], $body['process']['after']['fun'], $body['process']['after']['data']);
                    //给发起人发送已完成的消息
                    message(array(
                        "stid" => $audit['applicantId'],
                        "type" => $audit['flowName'],
                        "typeId" => $audit['id'],
                        "text" => "您提交的【{$audit['flowName']}】已通过",
                    ));
                }
                //添加审批记录
                auditingFollow([
                    "type" => $audit['flowName'],
                    "typeId" => $audit['id'],
                    "text" => "【{$this->control['name']}】转交了【{$audit['flowName']}】" . "【小程序】",
                    'remark' => '',
                    'source' => 'applet',
                    'staffName' => $this->control['name'],
                    'job' => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name']
                ]);
                //更新审批表
                $field = [
                    'approver' => implode(',', $result['staffName']),
                    'workFlow' => $result['isEnd'] ? '已通过' : '审核中',
                    'approverId' => implode(',', $result['staffId'])
                ];
                if ($result['nodeIsEnd']) {
                    $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
                }

                $warn = update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
                if ($warn == '更新成功') {
                    //待办提醒
                    self::sendTip($result['staffId'], $audit['id'], "【{$audit['applicantDepartment']}】-【{$audit['applicant']}】提交的【{$audit['flowName']}】需要您审批");
                }
                //更新待办
                backlogEnd(array(
                    "stid" => $this->control['stid'],
                    "typeId" => $audit['id'],
                ));
                $warn = '转交成功';
            } else {
                return '转交失败';
            }
        }
        return $warn;
    }


    public function rejectTheNode($flow, $audit, $text)
    {

        $result = self::findAuditPeople($flow);
        //更新当前审批人的待办
        backlogEnd(array(
            "stid" => $this->control['stid'],
            "typeId" => $audit['id'],
        ));
        //清除未处理的待办
        $this->clearBackLog($audit['id']);
        //添加审批记录
        auditingFollow([
            "type" => $audit['flowName'],
            "typeId" => $audit['id'],
            "text" => "【{$this->control['name']}】驳回了【{$audit['flowName']}】到指定节点" . ($text ? '，备注：' . $text : '')."【小程序】",
            'remark' => $text,
            'staffName' => $this->control['name'],
            'job' => self::findStaffDepartment(self::$stid) . '-' . $this->controlJob['name'],
        ]);

        if ($result['auditType'] == '审批人自选') {
            self::batchMessage([$audit['applicantId']], $audit['id'], str_replace(['{{flowName}}'], [$audit['flowName']], L('您的【{{flowName}}】需要选择审批人')));
        } else {
            //给下一审批人添加待办
            self::sendTip($result['staffId'], $audit['id'], '【'.$audit['applicantDepartment'].'】-【'.$audit['applicant'].'】提交的【'.$audit['flowName'].'】被【'.self::findStaff(self::$stid).'】驳回到您的节点，需要您重新审批'. ($text ? '，备注：' . $text : ''));
            self::findAutoNode($result['flow'], $audit['flowName'], $audit['id'], str_replace(['{{deptName}}', '{{staffName}}', '{{name}}'], [$audit['applicantDepartment'], $audit['applicant'], $audit['flowName']], L('【{{deptName}}】-【{{staffName}}】提交的【{{name}}】需要您审批')));
        }
        //更新审批表
        $field = [
            'approver' => implode(',', $result['staffName']),
            'workFlow' => $result['isEnd'] ? '已通过' : '审核中',
            'approverId' => implode(',', $result['staffId']),
        ];
        if ($result['nodeIsEnd']) {
            $field['commitTimePrevious'] = $this->time;//更新上节点提交时间
        }
        //更新审批表
        update(array('table' => 'audit', 'field' => $field, 'where' => "id = '$audit[id]'"));
    }

    /**
     * 审批人自选提交
     */
    public function addAuditPeopleEdit()
    {
        $staffIdArr = (array)json_decode($_POST['stid'], true);
        $id = $this->post('id');//提交数据的ID
        $body = $this->post('body');//加密参数
        $body = self::validateBody($body);
        $flow = (!is_array($body)) ? [] : self::findFlow($id, $body);
        $flag = false;
        foreach ($flow as $array) {
            if ($array['type'] == '审批人自选' && $array['state'] == '审核中' && $array['form'] == 'approver') {
                $flag = true;
                break;
            }
        }
        if (empty($staffIdArr) || !is_array($staffIdArr)) {
            $this->resp['warn'] = "未找到审批人";
        } elseif (!$flag) {
            $this->resp['warn'] = '此审批流程中没有审批人自选';
        } else {
            $staffId = [];
            foreach ($staffIdArr as $array) {
                $staffId[] = $array['stid'];
            }
            $staffId = array_unique($staffId);//去除重复
            $staffName = [];//员工姓名组装
            $stateBox = [];//状态组装
            foreach ($staffId as $stid) {
                $staff = query('staff', " stid = '$stid'");
                $staffName[] = $staff['name'];
//                $stateBox[$stid] = '审核中';
                $stateBox = self::updateStateNode($stateBox, '审核中', $stid, true);
            }
            foreach ($flow as $k => $array) {
                if ($array['type'] == '审批人自选' && $array['form'] == 'approver') {
                    $array['type'] = '指定成员';
                    $array['staff[]'] = implode(';', $staffId);
                    $array['staffName'] = implode(',', $staffName);
                    $array['stateNode'] = $stateBox;
                    $array['state'] = '审核中';
                    $flow[$k] = $array;
                    break;
                }
            }
            $warn = self::start($id, $body, $flow);
            if ($warn !== true) {
                $this->resp['warn'] = $warn;
            } else {
                $this->code = 1;
                $this->resp['warn'] = '提交成功';
            }
        }
    }


    /**
     * 获取员工列表
     */
    public function staff()
    {
        $where = '';
        if ($this->post('keyword')) {
            $where .= " and name like '%" . $this->post('keyword') . "%'";
        }

        $all = find(array('table' => 'staff', 'where' => "state !='离职' {$where} and workFlow = '已复核' order by time asc"));
        $data = [];
        $x = 0;
        $pinyinRange = [];
        foreach ($all['array'] as $array) {
            $x++;
            $job = query('job', "id = '$array[jobId]'");
            $pinyin = PYClass::encode($array['name']);
            $indexWord = strtoupper(mb_substr($pinyin, 0, 1));
            $data[] = [
                'stid' => $array['stid'],
                'title' => $array['name'],
                'ico' => self::fillSrc($array['ico'], $array['updateTime']),
                'department' => self::findStaffDepartment($array['stid']),
                'job' => $job['name'],
                'pinyin' => $pinyin,
                'index' => $indexWord
            ];
            if (!in_array($indexWord, $pinyinRange)) {
                $pinyinRange[] = $indexWord;
            }
        }
        $data = count($data) > 0 ? self::my_sort($data, 'pinyin', SORT_ASC, SORT_STRING) : 0;
        asort($pinyinRange);
        $result = [];
        foreach ($pinyinRange as $word) {
            $children = [];
            foreach ($data as $array) {
                if ($array['index'] == $word) {
                    $children[] = $array;
                }
            }
            $result[] = [
                'title' => $word,
                'index' => $word,
                'children' => $children
            ];
        }
        $this->code = 1;
        $this->resp['data']['result'] = $result;
        $this->resp['data']['total'] = $x;
    }

    /**
     * 执行函数
     *
     * @param string $cla
     * @param string $fun
     * @param array $data
     * @return string|bool
     */
    public static function call(string $cla, string $fun, $data = [])
    {
        if (!empty($cla) && !empty($fun)) {
            $cla = (stripos($cla, 'class') !== false) ? $cla : $cla . 'Class';
            $cla = __NAMESPACE__ . '\\' . $cla;
            $objClass = new $cla();
            if (method_exists($objClass, $fun)) {
                if (!empty($data) && is_array($data)) {
                    return $objClass->$fun($data);
                } else {
                    return $objClass->$fun();
                }
            } else {
                test($cla . '函数' . $fun . '不存在');
                return true;
            }
        }
        return false;
    }

    /**
     * 寻找下一审批人
     * @param $flow
     * @param string $type
     * @param string $chooseStid
     * @return array
     */
    public static function findAuditPeople($flow, $type = '', $chooseStid = ''): array
    {
        $staffName = [];//审批人姓名数组
        $staffId = [];//审批人ID数组
        $nodeIsEnd = false;//节点审批完成标志  true:完成
        $isEnd = false;//判断接下来是否还有审批
        $completeNode = 0;
        $auditType = '';//当前审批类型 //主要用于判断是否是审批人自选
        foreach ($flow as $k => $array) {
            if ($array['form'] == 'approver' && $array['type'] != '审批人自选') {
                $array['isAuto'] = $array['isAuto'] ?? '否';
                if ($array['isAuto'] === '是' && $array['state'] == '审核中') {
                    //自动审批节点
                    //此审批节点已通过
                    $flow[$k]['state'] = '已通过';
                    $nodeIsEnd = true;
                    $staffName = [];//员工姓名组装
                    $staffId = [];
                    $stateNode = [];
                    $auditStaff = explode(';', $array['staff[]']);//当前节点的审核人数组
                    $auditStaff = array_filter($auditStaff);
                    foreach ($auditStaff as $index => $stid) {
                        if ($array['multiType'] == '或签') {
                            $stateNode[] = [
                                'stid' => $stid,
                                'state' => $index == 0 ? '已通过' : '审核中'
                            ];
                        } else {
                            $stateNode[] = [
                                'stid' => $stid,
                                'state' => '已通过'
                            ];
                        }
                    }
                    $flow[$k]['state'] = '已通过';
                    $flow[$k]['stateNode'] = $stateNode;
                } elseif ($array['state'] == '审核中') {
                    if (empty($array['staff[]'])) {
                        //此审批节点已通过
                        $flow[$k]['state'] = '已通过';
                        $nodeIsEnd = true;
                        $staffName = [];//员工姓名组装
                        $staffId = [];
                    } else {
                        $auditStaff = explode(';', $array['staff[]']);//当前节点的审核人数组
                        $auditStaff = array_filter($auditStaff);
                        $stateNode = $array['stateNode'];//每个审批人审批状态集合
                        $stateBox = [];//状态组装
                        if ($type == '转交') {
                            foreach ($auditStaff as $stid) {
                                if ($stid == self::$stid) {
                                    $stid = $chooseStid;//转交人覆盖当前人
                                }
                                if ($chooseStid == $stid) {
                                    //如果转交的人已审批过，则需要再审批一次
                                    $stateBox[] = [
                                        'stid' => $stid,
                                        'state' => '审核中'
                                    ];
                                } else {
                                    $stateBox[] = [
                                        'stid' => $stid,
                                        'state' => self::returnState($stateBox, $stid) ?: '审核中'
                                    ];
                                }
                                $staff = query('staff', " stid = '$stid'");
                                $staffName[] = $staff['name'];
                                $staffId[] = $stid;
                            }
                        } else {
                            $stateBox = $stateNode;
                            $staffId = $auditStaff;
                            $staffName = explode(',', $array['staffName']);
                        }

                        $stName = array_unique(array_filter($staffName));
                        $staffId = array_unique(array_filter($staffId));//去重
                        $array['staff[]'] = implode(';', $staffId);
                        $array['staffName'] = implode(',', $stName);
                        $array['stateNode'] = $stateBox;
                        $flow[$k] = $array;
                        $state_res = self::returnStateCollection($stateBox);
                        if (in_array($array['multiType'], ['会签', '依次审批']) && in_array('审核中', $state_res)) {
                            //会签和依次审批必须全部审批完成
                            if ($array['multiType'] == '依次审批') {
                                $staffName = [];//员工姓名组装
                                $staffId = [];
                                //查找当前审批人
                                foreach ($stateBox as $item) {
                                    if ($item['state'] == '审核中') {
                                        $staff = query('staff', " stid = '$item[stid]'");
                                        $staffName[] = $staff['name'];
                                        $staffId[] = $item['stid'];
                                        break;
                                    }
                                }
                            } elseif ($array['multiType'] == '会签') {
                                $staffName = [];//员工姓名组装
                                $staffId = [];
                                //查找当前审批人
                                foreach ($stateBox as $item) {
                                    if ($item['state'] == '审核中') {
                                        $staff = query('staff', " stid = '$item[stid]'");
                                        $staffName[] = $staff['name'];
                                        $staffId[] = $item['stid'];
                                    }
                                }
                            }
                            break;
                        } elseif (in_array($array['multiType'], ['或签']) && !in_array('已通过', $stateBox)) {
                            //或签至少一人审批完成
                            break;
                        } else {
                            //此审批节点已通过
                            $flow[$k]['state'] = '已通过';
                            $nodeIsEnd = true;
                            $staffName = [];//员工姓名组装
                            $staffId = [];
                        }
                    }
                } else {
                    //此审批节点已通过
                    $nodeIsEnd = true;
                }
            } elseif ($array['form'] == 'approver' && $array['type'] == '审批人自选') {
                $staffName = [];//员工姓名组装
                $staffId = [];
                $auditType = '审批人自选';
                break;
            }
            $completeNode++;
        }

        if ($completeNode == count($flow) && $nodeIsEnd) {
            //此节点已结束且当前处于最后一节点
            $isEnd = true;
        }
        return ['flow' => $flow, 'auditType' => $auditType, 'staffId' => array_filter($staffId), 'staffName' => array_filter($staffName), 'nodeIsEnd' => $nodeIsEnd, 'isEnd' => $isEnd];
    }

    /**
     * 发送待办
     */
    public static function sendTip(array $staffId, string $auditId, string $text)
    {
        $info = query('audit', " id = '$auditId'");
        foreach ($staffId as $stid) {
            $staff = query('staff', "stid = '$stid'");
            $backlog = query('backlog', "typeId = '$auditId' and stid = '$stid' and workFlow = '待处理'");
            if (empty($backlog['id']) && $staff['state'] != '离职') {
                $id = self::getId();
                backlogIn([
                    'id' => $id,
                    "stid" => $stid,
                    "type" => $info['flowName'],
                    "typeId" => $auditId,
                    "text" => $text,
                ]);
                //发送小程序消息
                $content = [
                    [
                        'key' => '审批类型',
                        'value' => $info['flowName'],
                    ],
                    [
                        'key' => '内容',
                        'value' => $text,
                    ]
                ];
                $description = '发起时间：' . date('m-d H:i', strtotime($info['commitTime']));
                self::sendMiniProgramMessage([$stid], $content, $info['targetId'], $info['flowName'], $id, $description);
            }
        }
    }

    /**
     * 批量发送消息
     * @param array $staffId
     * @param string $auditId
     * @param string $text
     */
    public static function batchMessage(array $staffId, string $auditId, string $text)
    {
        $info = query('audit', " id = '$auditId'");
        foreach ($staffId as $stid) {
            $staff = query('staff', "stid = '$stid'");
            if ($staff['state'] != '离职') {
                message([
                    "stid" => $stid,
                    "type" => $info['flowName'],
                    "typeId" => $auditId,
                    "text" => $text,
                ]);
            }
        }
    }

    /**
     * 撤销审批
     *
     * @return string|bool
     */
    public static function cancel($id, $body)
    {
        $info = query($body['table'], " id = '$id' ");
        if (empty($info['id'])) {
            $warn = '记录不存在';
        } else {
            $where = self::flowWhere($body['name'] ?? '');
            $audit = query('audit', "targetId = '$id' {$where} order by time desc");
            $field = [];
            $keys = array_keys($info);
            // 提交时间 审核时间
            $fields = ['commitTime', 'passTime'];
            foreach ($fields as $key) {
                if (in_array($key, $keys)) {
                    $field[$key] = '';
                }
            }
            $field['examine'] = '';
            // 取消状态
            $warn = static::update([
                'table' => $body['table'],
                'field' => array_merge($field, self::getUpdateValue($body['field'], $body['value'])),
                'where' => " id = '$id' ",
            ]);
            if ($warn != '更新成功') {
                $warn = '撤销审批失败';
            } else {
                $warn = '撤销审批成功';
                //撤销企业微信消息
                self::revokeMessage($audit['id']);
                // 删除待办
                delete(['table' => 'backlog',
                    'where' => generateWhere([
                        'typeId' => $audit['id'],
                        'workFlow' => '待处理',
                    ]),
                ]);
                // 删除消息
                delete([
                    'table' => 'message',
                    'where' => generateWhere([
                        'typeId' => $audit['id'],
                        'see' => '否',
                    ]),
                ]);
                // 执行取消后的函数
                $process = $body['process']['after'];
                if (is_array($process) && !empty($process)) {
                    self::call($process['cla'], $process['fun'], $process['data'] ?? []);
                }
            }
        }
        return $warn;
    }

    /**
     * 构造更新参数
     *
     * @param array $field
     * @param array $data
     * @param bool $accept
     * @return array
     */
    private static function getUpdateValue($field, $data, $accept = true): array
    {
        $params = [];
        foreach ($field as $value) {
            if ($accept === true) {
                $params[$value] = $data[$value][0];
            } else {
                $params[$value] = $data[$value][1];
            }
        }
        return $params;
    }

    /**
     * 添加流程名称作为条件
     *
     * @param $flowName
     * @param string $orderNo
     * @return string
     */
    public static function flowWhere($flowName,$orderNo=''): string
    {
        $where = '';
        if ($flowName) {
            $where .= " and flowName = '$flowName'";
        }
        if ($orderNo){
            $where .= " and orderNo = '$orderNo'";
        }
        return $where;
    }

    /**
     * 寻找审批流程
     * @param $id
     * @param $body
     * @return array|string|null
     */
    public static function findFlow($id, $body)
    {
        $info = query($body['table'], " id = '$id' ");
        if (empty($info['id'])) {
            return '记录不存在';
        } else {
            //当前处于审批人自选阶段时
            if ($info['state'] == '审核中' && self::judgeSelfChoose(json_decode($info['examine'], true))) {
                $auditNode = json_decode($info['examine'], true);
            } else {
                // 判断审批流程是否存在
                $examine = query('examine', " target = '{$body['name']}' ");
                if (empty($examine)) {
                    return "【{$body['name']}】审批流程不存在，请确认";
                }
                if ($examine['state'] == '停用') {
                    return "【{$body['name']}】审批流程为停用状态，请确认";
                }
                // 所在范围
                $range = self::whereDoI(self::$stid);
                $array = (array)json_decode($examine['staff'], true);
                $examineRange = explode(';', $array['id'] ?? '');
                if (!array_intersect($range, $examineRange)) {
                    return "【{$body['name']}】审批流程未找到适用当前人的流程";
                }
                // 判断条件是否符合
                $condition = self::getCondition($examine, $info);
                if (!is_array($condition)) {
                    return $condition;
                }
                //判断部门负责人是否需要审批


                $cid = $condition['id'];
                $node = json_decode($examine['node'], true);
                // 根据类型选择更新审批节点，更新对应记录状态 审批人自选时，不发送待办
                $auditNode = [];
                // 上级
                $superior = explode(';', self::getSuperior(self::$stid));
                $superiorArray = self::filterArray($superior);
                foreach ($node[$cid] as $value) {
                    $arr = [];
                    switch ($value['type']) {
                        case '指定成员':
                            $arr = explode(';', $value['staff[]']);
                            break;
                        case '指定上级':
                        case '连续多级上级':
                            $arr = self::getSuperiorAppoint($value['type'], $value['value'], $superiorArray);
                            break;
                        case '指定职位':
                            $arr = self::getStaffIdByJob($value['staff[]']);
                            break;
                        case '部门负责人':
                            $arr = self::getDepartmentManager($id, $body, $value);
                            break;
                        case '审批人自选':
                            // 非本次处理流程
                            break;
                    }
                    if (!is_array($arr)) {
                        return $arr;
                    }
                    $arr = self::filterArray($arr);
                    $stateNode = [];
                    $flag = ($value['form'] == 'approver') ? '审核中' : '待抄送';
                    if (!empty($arr)) {
                        $value['staff[]'] = '';
                        $value['staffName'] = '';
                        if (!isset($value['staff[]'])) {
                            $value['staff[]'] = '';
                        }
                        foreach ($arr as $v) {
                            if (!self::isNull($v)) {
//                            $stateNode[$v] = $flag;
                                $stateNode[] = [
                                    'stid' => $v,
                                    'state' => $flag,
                                ];
                                $value['staff[]'] .= $v . ';';
                                $value['staffName'] = self::findStaff($v);
                            }
                        }
                    }
                    $value['state'] = $flag;
                    $value['stateNode'] = $stateNode;
                    $auditNode[] = $value;
                }
            }
            return $auditNode;
        }
    }

    /**
     * 获取部门负责人
     */
    public static function getDepartmentManager($id, $body, $data): array|string
    {
        $staffs = [];
        if ($data['value'] == '发起人部门负责人') {
            $staff = query('staff', "stid = '" . self::$stid . "'");
            $job = query('job', "id = '" . $staff['jobId'] . "'");
            $department = query('department', "id = '$job[departmentId]'");
            if (!empty($department['manager'])) {
                $staffs[] = $department['manager'];
            } else {
                return '未找到发起人的部门负责人';
            }
        } elseif ($data['value'] == '成员部门负责人') {
            $info = query($body['table'], " id = '$id' ");
            switch ($body['name'] == '入职申请') {
                case '入职申请':
                    $job = query('job', "id = '$info[jobId]'");
                    $department = query('department', "id = '$job[departmentId]'");
                    if (!empty($department['manager'])) {
                        $staffs[] = $department['manager'];
                    } else {
                        return '未找到此员工的部门负责人';
                    }
                    break;
                default:
                    $info['staffId'] = $info['staffId'] ?? $info['stid'];
                    $staff = query('staff', "stid = '$info[staffId]'");
                    $job = query('job', "id = '$staff[jobId]'");
                    $department = query('department', "id = '$job[departmentId]'");
                    if (!empty($department['manager'])) {
                        $staffs[] = $department['manager'];
                    } else {
                        return '未找到此员工的部门负责人';
                    }
                    break;
            }
        }
        return $staffs;
    }

    /**
     * 获取条件
     *
     * @param array $examine
     * @param array $info
     * @return string|array
     */
    public static function getCondition(array $examine, array $info)
    {
        $conditions = $original = (array)json_decode($examine['conditions'], true);
        if (empty($conditions)) {
            return "审批流程条件为空";
        }
        // 所在范围
        $range = self::whereDoI(self::$stid);
        foreach ($conditions as $key => $condition) {
            // 确定适用范围
            $examineRange = explode(';', $condition['staff[]']);
            $array = array_filter($examineRange);
            // 交集
            $result = array_intersect($range, $array);
            if (empty($result)) {
                unset($conditions[$key]);
            }
        }

        // 条件
        require_once "../../control/examineData.php";
        $array = isset($examineData[$examine['type']][$examine['target']]) ? array_keys($examineData[$examine['type']][$examine['target']]) : [];
        if ($array) {
            // 条件存在
//            $field = $array[0];
            foreach ($conditions as $key => $condition) {
                if (self::isNull($condition['field'])) {
                    continue;
                }
                $bool = self::getOperator($info[$condition['field']], $condition['value'], $condition['range']);
                if ($bool !== true) {
                    unset($conditions[$key]);
                }
            }
        }
        // 为空
        if (empty($conditions)) {
            $condition = [];
            foreach ($original as $value) {
                if ($value['name'] == '默认条件') {
                    $condition = $value;
                }
            }
            if (empty($condition)) {
                return "该审批流程暂无默认条件";
            } else {
                return $condition;
            }
        } else {
            // 选择优先级高的条件
            $last_names = array_column($conditions, 'level');
            array_multisort($last_names, SORT_DESC, $conditions);
            return $conditions[0];
        }
    }

    /**
     * 比较结果
     *
     * @param string $data
     * @param string $data2
     * @param string $operator
     * @return bool
     */
    public static function getOperator(string $data, string $data2, string $operator): bool
    {
        $bool = false;
        switch ($operator) {
            case '大于':
                $bool = ($data > $data2);
                break;
            case '大于等于':
                $bool = ($data >= $data2);
                break;
            case '等于':
                $bool = ($data == $data2);
                break;
            case '小于':
                $bool = ($data < $data2);
                break;
            case '小于等于':
                $bool = ($data <= $data2);
                break;
            case '介于':
                // 左开右闭 (]
                if (is_numeric($data)) {
                    $array = explode(',', $data2);
                    $bool = ($array[0] < $data && $data <= $array[1]);
                }
                break;
        }
        return $bool;
    }

    /**
     * 获取我的上级
     *
     * @return string
     */
    public static function getSuperior($stid): string
    {
        $temp = '';
        $info = query('staff', " stid = '$stid' ");
        if ($info['manager']) {
            $temp .= $info['manager'] . ';';
            $temp .= self::getSuperior($info['manager']);
        }
        return $temp;
    }

    /**
     * 根据职位寻找审批人
     */
    public static function getStaffIdByJob($jobList): array
    {
        $data = [];
        $array = explode(';', $jobList);
        foreach ($array as $jobId) {
            $result = find(array('table' => 'staff', 'where' => "state in ('转正','试用','留职') and jobId = '$jobId' order by time asc"));
            foreach ($result['array'] as $staff) {
                $data[] = $staff['stid'];
            }
        }
        return $data;
    }

    /**
     * 获取指定上级数据
     *
     * @param string $type 类型
     * @param string $key 层级
     * @param array $arr 数据
     * @return array
     */
    public static function getSuperiorAppoint(string $type, string $key, array $arr): array
    {
        if ($type == '指定上级') {
            $search = ['直接上级', '第二级上级', '第三级上级', '第四级上级', '第五级上级', '第六级上级', '第七级上级', '第八级上级', '第九级上级', '第十级上级',];
            $replace = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
            $key = str_replace($search, $replace, $key) - 1;
            return [$arr[$key]];
        } else {
            $search = ['最高上级', '第二级上级', '第三级上级', '第四级上级', '第五级上级', '第六级上级', '第七级上级', '第八级上级', '第九级上级', '第十级上级',];
            $replace = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
            $key = str_replace($search, $replace, $key);
            return $key == 0 ? array_slice($arr, $key) : array_slice($arr, 0, $key + 1);
        }
    }

    /**
     * 员工所在部门、职位、个人id的集合
     *
     * @param string $stid
     * @return array
     */
    public static function whereDoI(string $stid): array
    {
        $data = [$stid];
        // 获取职位所在
        $jobId = self::findStaff($stid, 'jobId');
        array_push($data, $jobId);
        // 初始部门id
        $departmentId = self::findStaffDepartment($stid, 'id');
        // 获取部门所在集合
        $string = self::getDepartmentId($departmentId);
        $array = explode(';', $string);
        $result = self::filterArray($array);
        return array_merge($data, $result);
    }

    /**
     * 获取 部门id
     *
     * @param string $id
     * @return string
     */
    public static function getDepartmentId(string $id)
    {
        $temp = '';
        $info = query('department', " id = '$id' ");
        if ($info['id']) {
            $temp .= $info['id'] . ';';
            if (!empty($info['pid'])) {
                $temp .= self::getDepartmentId($info['pid']);
            }
        }
        return $temp;
    }

    /**
     * 是否为一位数组
     */
    public static function is_single_array($array): bool
    {
        if (count($array) == count($array, 1) && count($array) > 0) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 本次操作是否有权限，包括审核、撤销
     *
     * @param string $table
     * @param string $targetId
     * @param string $type
     * @param null $flowName
     * @return bool
     */
    public static function auditFlag(string $table, string $targetId, $type = 'approver', $flowName = null): bool
    {
        $bool = false;
        $data = query($table, " id = '$targetId' ");
        if ($data['id']) {
            $field = array_key_exists('auditing', $data) ? 'auditing' : 'examine';
            //审核流程
            $auditing = (array)json_decode($data[$field], true);
            switch ($type) {
                // 撤销审批 当前人在审批人中
                case 'cancel':
                    $is_single = false;
                    $approver = [];
                    foreach ($auditing as $key => $val) {
                        if ($val['form'] == 'approver') {
                            if (self::is_single_array($val['stateNode'])) {
                                $is_single = true;
                                $approver = array_merge($val['stateNode'], $approver);
                            } else {
                                $approver = array_merge(self::returnStidCollection($val['stateNode']), $approver);
                            }
                        }
                    }
                    $bool = $is_single ? in_array(self::$stid, array_keys($approver)) : in_array(self::$stid, $approver);
                    break;
                // 审核
                case 'approver':
                    $where = self::flowWhere($flowName);
                    $audit = query('audit', "targetId = '$targetId' {$where} order by time desc");
                    $bool = in_array(self::$stid, array_filter(explode(',', $audit['approverId'])));
                    break;
                case 'selfChoose':
                    //判断是否存在审批人自选
                    $bool = false;
                    foreach ($auditing as $val) {
                        if ($val['form'] == 'approver' && $val['state'] == '审核中' && $val['type'] == '审批人自选') {
                            $bool = true;
                        } elseif ($val['form'] == 'approver' && $val['state'] == '审核中') {
                            break;
                        }
                    }
                    break;
            }
        }
        return $bool;
    }

    /**
     * 获取当前审批角色
     * @param string $table 表名
     * @param string $id ID
     * @param string $flowName 流程名称
     * @param string $stid 提交人
     * @return string
     */
    public static function role(string $table, string $id, $flowName = '', $stid = 'stid'): string
    {
        $role = '';
        $data = query($table, " id = '$id' ");
        if ($data['id']) {
            if (in_array($flowName, ['加班申请', '外出申请', '加班成果审核', '外出成果审核', '出差申请', '出差成果审核'])) {
                if ($data['state'] == '草稿' && self::$stid == $data[$stid]) {
                    //申请人提交
                    $role = 'editor';
                } elseif ($data['state'] == '审核中' && auditAppClass::auditFlag($table, $id, 'selfChoose')) {
                    //自选
                    $role = 'selfChoose';
                } elseif (($data['state'] == '审核中' || $data['state'] == '审核成果') && auditAppClass::auditFlag($table, $id, flowName: $flowName)) {
                    $role = 'auditor';
                } elseif (($data['state'] == '审核中' || $data['state'] == '审核成果') && self::$stid == $data[$stid]) {
                    $role = 'editor';
                } elseif ($data['state'] == '已通过' && self::$stid == $data[$stid]) {
                    $role = 'editor';
                } elseif (($data['state'] == '已通过' || $data['state'] == '成果确认') && auditAppClass::auditFlag($table, $id, 'cancel', $flowName)) {
                    $role = 'auditor';
                }
            } elseif ($data['state'] == '草稿' && self::$stid == $data[$stid]) {
                //申请人提交
                $role = 'editor';
            } elseif ($data['state'] == '审核中' && auditAppClass::auditFlag($table, $id, 'selfChoose')) {
                //自选
                $role = 'selfChoose';
            } elseif ($data['state'] == '审核中' && auditAppClass::auditFlag($table, $id)) {
                $role = 'auditor';
            } elseif ($data['state'] == '审核中' && self::$stid == $data[$stid]) {
                $role = 'editor';
            } elseif ($data['state'] == '已通过' && auditAppClass::auditFlag($table, $id, 'cancel')) {
                $role = 'auditor';
            }
        }
        return $role;
    }


    /**
     * 审批记录
     *
     * @param string $table
     * @param string $targetId
     */
    public static function auditRecord(string $table, string $targetId, $flowName = ''): bool|array
    {
        //数据库查询
        $info = query($table, " id = '$targetId' ");
        $where = '';
        if ($flowName) {
            $where = " and flowName = '$flowName'";
        }
        $audit = query('audit', " targetId = '$targetId'" . $where);
        if (self::isNull($audit['id'])) {
            return false;
        } else {
            $examine = (array)json_decode($info['examine'], true);
            // 获取本次审核中的结果集
            $result = array_filter($examine, function ($arr) {
                return $arr['state'] == '审核中';
            });
            $record_list = [];
            $active = 0;
            $x = 0;
            $record_list[] = [
                'index' => 0,
                'text' => "【{$audit['applicant']}】提交了{$audit['flowName']} " . $audit['commitTime'],
            ];
            foreach ($examine as $k => $array) {
                $x++;
                // 当前进度
                if (in_array($array['state'], ['已通过', '已抄送'])) {
                    $style = 'done';
                } elseif (in_array($array['state'], ['已驳回'])) {
                    $style = 'done';
                } elseif ($array['state'] == '审核中' && $array['id'] == reset($result)['id']) {
                    // 判断当前流程是否是第一个待审核流程
                    $style = 'current';
                } else {
                    $style = 'none';
                }
                $string = '';
                if ($array['type'] == '审批人自选') {
                    $string = '审批人自选';
                } else {
                    foreach ($array['stateNode'] as $node) {
                        if (in_array($array['state'], ['已通过', '已驳回']) && in_array(self::returnState($array['stateNode'], $node['stid']), ['审核中', '待抄送'])) {
                            continue;
                        }
                        $text = '';
                        if (is_array($node)) {
                            switch ($node['state']) {
                                case '已通过':
                                case '已驳回':
                                    $state = ($node['state'] == '已通过') ? '通过' : '驳回';
                                    $record = query('backlog', " `stid` = '$node[stid]' AND `workFlow`='已完成' AND `typeId` = '{$audit['id']}' ORDER BY updateTime DESC ");
                                    $text = '【' . self::findStaff($node['stid']) . '】' . $state . '了' . $audit['flowName'] . (!empty($array['auditFollow'][$node['stid']]) ? '，' . $array['auditFollow'][$node['stid']] : '');
                                    break;
                                case '已抄送':
                                    $record = query('message', " `stid` = '$node[stid]' AND `typeId` = '{$audit['id']}' ORDER BY time DESC  ");
                                    $text = '【' . self::findStaff($node['stid']) . '】抄送了' . $audit['flowName'];
                                    break;
                                default:
                                    $record = [];
                                    $text = '【' . self::findStaff($node['stid']) . '】' . ($array['form'] == 'approver' ? '审核中' : '待抄送');
                                    break;
                            }
                        }
                        $string .= $text . ' ' . ($record['updateTime'] ?? '') . "\n";
                    }
                }

                // 类型
                $record_list[] = [
                    'index' => $k + 1,
                    'text' => $string
                ];
                if ($style == 'current') {
                    $active = $k + 1;
                }
            }
            //已完成的
            $active = ($x > 0 && $active == 0) ? ($x + 1) : $active;
            return ['active' => $active, 'record' => $record_list];
        }
    }

    /**
     * 撤销发送的企业微信消息
     * @param $auditId
     */
    public static function revokeMessage($auditId)
    {
        $all = find(array('table' => 'backlog', 'where' => "typeId='$auditId' and workFlow = '待处理'"));
        foreach ($all['array'] as $array) {
            $message = query('message_we_chat', "messageId = '$array[id]'");
            if (!empty($message['id'])) {
                self::revokeQyMessage($message['qyMessageId']);
            }
        }
    }

    /**
     * 生成已处理待办
     */
    public static function generateDoneTip($auditStaff, $flowName, $auditId, $text)
    {
        if (is_array($auditStaff)) {
            foreach ($auditStaff as $stid) {
                $warn = static::insert(array(
                    'table' => 'backlog',
                    'field' => array(
                        'id' => self::getId(),
                        "stid" => $stid,
                        "type" => $flowName,
                        "typeId" => $auditId,
                        "text" => $text,
                        "startDay" => date('Y-m-d'),
                        'workFlow' => '已完成'
                    )
                ));
            }
        }
    }

    /**
     * 找到需要发送待办的自动审批节点，写入已处理待办
     */
    public static function findAutoNode($flow, $flowName, $auditId, $text)
    {
        $staffs = [];//需要增加已处理待办的员工ID数组
        foreach ($flow as $array) {
            $array['isAuto'] = $array['isAuto'] ?? '否';
            if ($array['form'] == 'approver') {
                if ($array['state'] == '审核中') {
                    //遇到目前审核中状态的节点，则退出
                    break;
                }
                if ($array['isAuto'] == '是') {
                    $auditStaff = explode(';', $array['staff[]']);//当前节点的审核人数组
                    $auditStaff = array_filter($auditStaff);
                    if ($array['multiType'] == '或签') {
                        $auditStaff = isset($auditStaff[0]) ? [$auditStaff[0]] : [];
                    }
                    $staffs = $auditStaff;
                } else {
                    //遇到非自动审批节点，则清空已发送了待办的员工数组ID
                    $staffs = [];
                }
            }
        }
        self::generateDoneTip($staffs, $flowName, $auditId, $text);
    }

    /**
     * @param array $stids 员工数组
     * @param array $content 内容  array(['key'=>'','value'=>''])
     * @param string $targetId 对象ID
     * @param string $target 类型
     * @param string $messageId 关联的待办ID
     */
    public static function sendMiniProgramMessage(array $stids, $content, $targetId, $target, $messageId, $description = '')
    {
        $whileField = [
            '付款申请' => '/oa/pages/paymentInfo/paymentInfo?id=' . $targetId,
            '费用报销' => '/oa/pages/costInfo/costInfo?id=' . $targetId,
            '费用申请' => '/oa/pages/feeApplyInfo/feeApplyInfo?id=' . $targetId,
            '外出申请' => '/oa/pages/workOutInfo/workOutInfo?id=' . $targetId,
            '外出成果审核' => '/oa/pages/workOutInfo/workOutInfo?id=' . $targetId,
            '出差申请' => '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $targetId,
            '出差成果审核' => '/oa/pages/bussinessTripDetail/bussinessTripDetail?id=' . $targetId,
            '加班申请' => '/oa/pages/workInfo/workInfo?id=' . $targetId,
            '加班成果审核' => '/oa/pages/workInfo/workInfo?id=' . $targetId,
            '补卡申请' => '/oa/pages/workSignAddInfo/workSignAdInfo?id=' . $targetId,
            '请假申请' => '/oa/pages/workHolidayInfo/workHolidayInfo?id=' . $targetId,
        ];
        if (in_array($target, array_keys($whileField))) {
            $user_sertting = query('user_setting', "stid = '" . self::$stid . "' and type = 'OA通知设置'");
            $setting = json_decode($user_sertting['value'], true);
            $setting['message'] = $setting['message'] ?? '';
            if ($setting['message']) {
                //设置打开，则发送消息
                $result = self::sendQYWechatMessage($stids, '待审批提醒', $content, $whileField[$target], $description);
                if ($result !== false) {
                    $msgId = $result['msgid'];
                    foreach ($stids as $stid) {
                        $staff = query('staff', "stid = '$stid'");
                        if ($staff != '离职') {
                            static::insert(array(
                                'table' => 'message_we_chat',
                                'field' => [
                                    'stid' => $stid,
                                    'targetId' => $targetId,
                                    'target' => $target,
                                    'messageId' => $messageId,
                                    'qyMessageId' => $msgId
                                ]
                            ));
                        }
                    }
                }
            }
        }
    }

}
